package org.pyneo.tabulae.screencapture;
import android.app.Activity;
import android.content.Context;
import android.os.Build;
import android.content.Intent;
import android.hardware.display.DisplayManager;
import android.hardware.display.VirtualDisplay;
import android.media.MediaRecorder;
import android.media.projection.MediaProjection;
import android.media.projection.MediaProjectionManager;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.util.Log;
import android.widget.Toast;
import java.io.File;
import java.util.Date;
import java.util.TimeZone;
import org.pyneo.tabulae.Base;
import org.pyneo.tabulae.R;
import org.pyneo.tabulae.Tabulae;
import static org.pyneo.tabulae.screencapture.Constants.*;
public class ScreenCaptureFragment extends Base {
private static final String STATE_ENABLED = "screencapture_enabled";
private static final String STATE_RESULT_CODE = "screencapture_result_code";
private static final String STATE_RESULT_DATA = "screencapture_result_data";
protected boolean enabled;
protected int mScreenWidth;
protected int mScreenHeight;
protected int mScreenDensity;
protected MediaProjectionManager mMediaProjectionManager;
protected MediaProjection mMediaProjection;
protected VirtualDisplay mVirtualDisplay;
protected MediaRecorder mMediaRecorder;
private int mResultCode;
private Intent mResultData;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (DEBUG) Log.d(TAG, "ScreenCaptureFragment.onCreate");
if (savedInstanceState != null) {
enabled = savedInstanceState.getBoolean(STATE_ENABLED);
mResultCode = savedInstanceState.getInt(STATE_RESULT_CODE);
mResultData = savedInstanceState.getParcelable(STATE_RESULT_DATA);
}
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (DEBUG) Log.d(TAG, "ScreenCaptureFragment.onActivityCreated enabled=" + enabled + ", mVirtualDisplay=" + mVirtualDisplay);
Activity activity = getActivity();
DisplayMetrics mDisplayMetrics = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(mDisplayMetrics);
mScreenDensity = mDisplayMetrics.densityDpi;
mScreenWidth = mDisplayMetrics.widthPixels;
mScreenHeight = mDisplayMetrics.heightPixels;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
mMediaProjectionManager = (MediaProjectionManager) activity.getSystemService(Context.MEDIA_PROJECTION_SERVICE);
}
else {
; // TODO
}
mMediaRecorder = new MediaRecorder();
if (enabled && mVirtualDisplay == null) {
go();
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (DEBUG) Log.d(TAG, "ScreenCaptureFragment.onSaveInstanceState mResultData=" + mResultData + ", mResultCode=" + mResultCode);
outState.putBoolean(STATE_ENABLED, enabled);
if (mResultData != null) {
outState.putInt(STATE_RESULT_CODE, mResultCode);
outState.putParcelable(STATE_RESULT_DATA, mResultData);
}
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent resultData) {
if (DEBUG) Log.d(TAG, "ScreenCaptureFragment.onActivityResult resultCode=" + resultCode + ", requestCode=" + requestCode + ", resultData=" + resultData);
switch (requestCode) {
case R.id.activity_result_id_screencapture: {
switch (resultCode) {
case Activity.RESULT_OK: {
enabled = true;
mResultCode = resultCode;
mResultData = resultData;
if (DEBUG) Log.d(TAG, "ScreenCaptureFragment.onActivityResult: permission granted enabled=" + enabled);
if (getActivity() != null) {
go();
}
}
break;
default:
if (DEBUG) Log.d(TAG, "ScreenCaptureFragment.onActivityResult: permission denied");
stopRecording();
Toast.makeText(getActivity(), "User canceled", Toast.LENGTH_SHORT).show();
}
}
default:
super.onActivityResult(requestCode, resultCode, resultData);
}
}
@Override
public void onDestroy() {
super.onDestroy();
if (DEBUG) Log.d(TAG, "ScreenCaptureFragment.onDestroy");
if (mMediaProjection != null) {
try {
mMediaProjection.stop();
}
catch (Exception ignore) {
Log.e(TAG, "ScreenCaptureFragment.onDestroy:", ignore);
}
finally {
mMediaProjection = null;
}
}
}
@Override
public void onPause() {
super.onPause();
stopRecording();
}
protected void go() {
if (DEBUG) Log.d(TAG, "ScreenCaptureFragment.go mResultData=" + mResultData + ", mResultCode=" + mResultCode);
if (getActivity() != null) {
if (mResultData != null && mMediaProjection == null) {
mMediaProjection = mMediaProjectionManager.getMediaProjection(mResultCode, mResultData);
// mMediaProjection.registerCallback(...
}
if (DEBUG) Log.d(TAG, "ScreenCaptureFragment.go mMediaProjection=" + mMediaProjection);
if (mMediaProjection != null && mVirtualDisplay == null) {
try {
if (DEBUG) Log.d(TAG, "mScreenWidth=" + mScreenWidth + ", mScreenHeight=" + mScreenHeight);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
// mMediaRecorder.setVideoEncodingBitRate(128 * 1000);
// mMediaRecorder.setVideoFrameRate(12);
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
mScreenWidth = ((mScreenWidth + 15) / 16) * 16; // round up to multiple of 16
mMediaRecorder.setVideoSize(mScreenWidth, mScreenHeight);
mMediaRecorder.setOutputFile(getMovieName().getPath());
mMediaRecorder.prepare();
mMediaRecorder.start();
mVirtualDisplay = mMediaProjection.createVirtualDisplay(
getClass().getSimpleName(),
mScreenWidth,
mScreenHeight,
mScreenDensity,
DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
mMediaRecorder.getSurface(),
null, // Callbacks
null // Handler
);
if (DEBUG) Log.d(TAG, "ScreenCaptureFragment.onActivityResult: recording started");
Toast.makeText(getActivity(), "Recording started", Toast.LENGTH_SHORT).show();
}
catch (Exception e) {
Toast.makeText(getActivity(), e.getMessage(), Toast.LENGTH_SHORT).show();
Log.e(TAG, "ScreenCaptureFragment.onActivityResult:", e);
stopRecording();
}
}
}
}
protected void startRecording() {
if (mVirtualDisplay != null) {
stopRecording();
}
if (mMediaProjection == null) {
getActivity().startActivityForResult(mMediaProjectionManager.createScreenCaptureIntent(), R.id.activity_result_id_screencapture);
enabled = true;
Bundle extra = new Bundle();
extra.putBoolean("enabled", enabled);
((Tabulae)getActivity()).inform(R.id.event_notify_screencapture, extra);
if (DEBUG) Log.d(TAG, "ScreenCaptureFragment.startRecording: ask for permission enabled=" + enabled);
} else {
go();
}
}
protected void stopRecording() {
enabled = false;
Bundle extra = new Bundle();
extra.putBoolean("enabled", enabled);
((Tabulae)getActivity()).inform(R.id.event_notify_screencapture, extra);
if (mVirtualDisplay != null) {
try {
mVirtualDisplay.release();
}
catch (Exception ignore) {
// Log.e(TAG, "ScreenCaptureFragment.stopRecording:", ignore);
}
finally {
mVirtualDisplay = null;
}
}
if (mMediaRecorder != null) {
try {
mMediaRecorder.stop();
}
catch (Exception ignore) {
// Log.e(TAG, "ScreenCaptureFragment.stopRecording:", ignore);
}
finally {
mMediaRecorder.reset();
mMediaRecorder.release();
}
}
if (DEBUG) Log.d(TAG, "ScreenCaptureFragment.stopRecording: recording stopped");
}
File getMovieName() {
File f;
do {
ISODATEFORMAT.setTimeZone(TimeZone.getTimeZone("UTC"));
f = new File(((Tabulae) getActivity()).getMoviesDir(), ISODATEFORMAT.format(new Date()) + "-capture.mp4");
}
while (f.exists());
if (DEBUG) Log.d(TAG, "getMovieName f=" + f);
return f;
}
public void inform(int event, Bundle extra) {
switch (event) {
case R.id.event_request_screencapture: {
if (getActivity() != null) {
Bundle b = new Bundle();
b.putBoolean("enabled", enabled);
((Tabulae)getActivity()).inform(R.id.event_notify_screencapture, b);
}
}
break;
case R.id.event_do_screencapture: {
if (enabled) {
stopRecording();
Toast.makeText(getActivity(), "Recording stopped", Toast.LENGTH_SHORT).show();
} else {
startRecording();
}
}
break;
}
}
}